#pragma once

#include <libtcod/libtcod.hpp>

#include <memory>
#include <string>
#include <functional>

namespace Views { class ViewManager; }

class Kernel; typedef std::shared_ptr<Kernel> KernelPtr;
class Kernel
{
public:
	static KernelPtr getSingleton();
	static void Shutdown();
	~Kernel();

	void config(const std::string &resource_dir);
	void init(int argc, char** argv);
	void initScene(); //Will be deprecated at some point...

	void run();
	void exit() { running = false; }
	bool isRunning() const { return running; }

	void update(float dt);
	void render();
	void reshape(int w, int h);
	void inputKeyDown();
	void inputKeyUp();
	void motion();
	void mousePressed();
	void mouseReleased();

	int getPrevTime(int cur_time) { auto tmp_time = prev_time; prev_time = cur_time; return tmp_time; }
	int getStartTime() const { return start_time; }
	int getElapsedTime(int cur_time) const { return cur_time - start_time; }
	int getTimeSincePrevFrame(int cur_time) { return cur_time - getPrevTime(cur_time); }

public:
	const std::string &getResourceDir() const { return resource_dir; }
	int getWidth() const { return width; }
	int getHeight() const { return height; }
	int getDepth() const { return depth; }
	int getRefreshRate() const { return refresh_rate; }
	int getLogicUpdateRate() const { return logic_update_rate; }
	int getFullscreen() const { return fullscreen; }
	int getGameMode() const { return game_mode; }
	std::string getGameModeString() const;
	int getOpenGLVersionMajor() const { return opengl_major_version; }
	int getOpenGLVersionMinor() const { return opengl_minor_version; }
	std::string getOpenGLVersionString() const;

private:
#if(_MSC_VER >= 1700)
	friend class std::_Ref_count_obj<Kernel>;
#else
	friend class std::tr1::_Ref_count_obj<Kernel>;
#endif
	static KernelPtr singleton;
	Kernel();

	std::string resource_dir;

	int width;
	int height;
	int depth;
	int refresh_rate;
	int logic_update_rate;
	int fullscreen;
	int game_mode;
	int opengl_major_version;
	int opengl_minor_version;

	bool running;
	int start_time;
	int prev_time;

private:
	TCOD_key_t key;
	TCOD_mouse_t mouse;

private:
	std::unique_ptr<Views::ViewManager> viewMgr;
};
